Pass ChangeInfo object to extension panels Instead of the change ID pass the ChangeInfo object to extension panels of the change screen. This makes all change data available to the plugin UI code and the plugin doesn't need to load the change data once more if it is needed. To make this work the ChangeInfo class must be in a package that is both visible to the Gerrit client and the plugins. This is why ChangeInfo and all *Info classes that are imported into ChangeInfo are moved to gerrit-gwtui-common. ChangeInfo also uses classes from: - //lib:gwtjsonrpc - //lib:gwtorm_client - //gerrit-common:client - //gerrit-reviewdb:client This is why these dependencies are added to gerrit-gwtui-common. They are exported by gerrit-plugin-gwtui so that they are available to GWT plugins. Change-Id: I52d6c5cd68e3c05c66a6d68c2cef10a1df54948f Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/gerrit-gwtui-common/BUCK b/gerrit-gwtui-common/BUCK index 2eb0684..6ee0336 100644 --- a/gerrit-gwtui-common/BUCK +++ b/gerrit-gwtui-common/BUCK
@@ -1,3 +1,12 @@ +EXPORTED_DEPS = [ + '//gerrit-common:client', + '//gerrit-gwtexpui:Clippy', + '//gerrit-gwtexpui:GlobalKey', + '//gerrit-gwtexpui:Progress', + '//gerrit-gwtexpui:SafeHtml', + '//gerrit-gwtexpui:UserAgent', +] +DEPS = ['//lib/gwt:user'] SRC = 'src/main/java/com/google/gerrit/' DIFFY = glob(['src/main/resources/com/google/gerrit/client/diffy*.png']) @@ -6,7 +15,8 @@ srcs = glob([SRC + 'client/**/*.java']), gwt_xml = SRC + 'GerritGwtUICommon.gwt.xml', resources = glob(['src/main/**/*']), - deps = ['//lib/gwt:user'], + exported_deps = EXPORTED_DEPS, + provided_deps = DEPS, visibility = ['PUBLIC'], ) @@ -20,7 +30,8 @@ name = 'client-lib2', srcs = glob(['src/main/**/*.java']), resources = glob(['src/main/**/*']), - provided_deps = ['//lib/gwt:user'], + exported_deps = EXPORTED_DEPS, + provided_deps = DEPS, visibility = ['PUBLIC'], )
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml b/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml index eb551c4..c147195 100644 --- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/GerritGwtUICommon.gwt.xml
@@ -14,5 +14,13 @@ limitations under the License. --> <module> + <inherits name='org.eclipse.jgit.JGit'/> + <inherits name='com.google.gerrit.Common'/> + <inherits name='com.google.gerrit.extensions.Extensions'/> + <inherits name='com.google.gerrit.prettify.PrettyFormatter'/> + <inherits name='com.google.gwtexpui.clippy.Clippy'/> + <inherits name='com.google.gwtexpui.globalkey.GlobalKey'/> + <inherits name='com.google.gwtexpui.progress.Progress'/> + <inherits name='com.google.gwtexpui.safehtml.SafeHtml'/> <source path='client' /> </module>
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java index e22625c..61f73c0 100644 --- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/GerritUiExtensionPoint.java
@@ -34,6 +34,6 @@ PROJECT_INFO_SCREEN_TOP, PROJECT_INFO_SCREEN_BOTTOM; public enum Key { - ACCOUNT_INFO, CHANGE_ID, PROJECT_NAME + ACCOUNT_INFO, CHANGE_INFO, PROJECT_NAME } } diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ActionInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ActionInfo.java new file mode 100644 index 0000000..3b283ec --- /dev/null +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ActionInfo.java
@@ -0,0 +1,29 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.client.info; + +import com.google.gwt.core.client.JavaScriptObject; + +public class ActionInfo extends JavaScriptObject { + + public final native String id() /*-{ return this.id; }-*/; + public final native String method() /*-{ return this.method; }-*/; + public final native String label() /*-{ return this.label; }-*/; + public final native String title() /*-{ return this.title; }-*/; + public final native boolean enabled() /*-{ return this.enabled || false; }-*/; + + protected ActionInfo() { + } +} diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java new file mode 100644 index 0000000..695c126 --- /dev/null +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java
@@ -0,0 +1,426 @@ +// Copyright (C) 2012 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.client.info; + +import com.google.gerrit.client.rpc.NativeMap; +import com.google.gerrit.client.rpc.NativeString; +import com.google.gerrit.client.rpc.Natives; +import com.google.gerrit.common.data.LabelValue; +import com.google.gerrit.common.data.SubmitRecord; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArray; +import com.google.gwt.core.client.JsArrayString; +import com.google.gwtjsonrpc.client.impl.ser.JavaSqlTimestamp_JsonSerializer; + +import java.sql.Timestamp; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +public class ChangeInfo extends JavaScriptObject { + public final void init() { + if (allLabels() != null) { + allLabels().copyKeysIntoChildren("_name"); + } + } + + public final Project.NameKey projectNameKey() { + return new Project.NameKey(project()); + } + + public final Change.Id legacyId() { + return new Change.Id(_number()); + } + + public final Timestamp created() { + Timestamp ts = _getCts(); + if (ts == null) { + ts = JavaSqlTimestamp_JsonSerializer.parseTimestamp(createdRaw()); + _setCts(ts); + } + return ts; + } + + public final boolean hasEditBasedOnCurrentPatchSet() { + JsArray<RevisionInfo> revList = revisions().values(); + RevisionInfo.sortRevisionInfoByNumber(revList); + return revList.get(revList.length() - 1).isEdit(); + } + + private final native Timestamp _getCts() /*-{ return this._cts; }-*/; + private final native void _setCts(Timestamp ts) /*-{ this._cts = ts; }-*/; + + public final Timestamp updated() { + return JavaSqlTimestamp_JsonSerializer.parseTimestamp(updatedRaw()); + } + + public final String idAbbreviated() { + return new Change.Key(changeId()).abbreviate(); + } + + public final Change.Status status() { + return Change.Status.valueOf(statusRaw()); + } + + public final Set<String> labels() { + return allLabels().keySet(); + } + + public final native String id() /*-{ return this.id; }-*/; + public final native String project() /*-{ return this.project; }-*/; + public final native String branch() /*-{ return this.branch; }-*/; + public final native String topic() /*-{ return this.topic; }-*/; + public final native String changeId() /*-{ return this.change_id; }-*/; + public final native boolean mergeable() /*-{ return this.mergeable ? true : false; }-*/; + public final native int insertions() /*-{ return this.insertions; }-*/; + public final native int deletions() /*-{ return this.deletions; }-*/; + private final native String statusRaw() /*-{ return this.status; }-*/; + public final native String subject() /*-{ return this.subject; }-*/; + public final native AccountInfo owner() /*-{ return this.owner; }-*/; + private final native String createdRaw() /*-{ return this.created; }-*/; + private final native String updatedRaw() /*-{ return this.updated; }-*/; + public final native boolean starred() /*-{ return this.starred ? true : false; }-*/; + public final native boolean reviewed() /*-{ return this.reviewed ? true : false; }-*/; + public final native NativeMap<LabelInfo> allLabels() /*-{ return this.labels; }-*/; + public final native LabelInfo label(String n) /*-{ return this.labels[n]; }-*/; + public final native String currentRevision() /*-{ return this.current_revision; }-*/; + public final native void setCurrentRevision(String r) /*-{ this.current_revision = r; }-*/; + public final native NativeMap<RevisionInfo> revisions() /*-{ return this.revisions; }-*/; + public final native RevisionInfo revision(String n) /*-{ return this.revisions[n]; }-*/; + public final native JsArray<MessageInfo> messages() /*-{ return this.messages; }-*/; + public final native void setEdit(EditInfo edit) /*-{ this.edit = edit; }-*/; + public final native EditInfo edit() /*-{ return this.edit; }-*/; + public final native boolean hasEdit() /*-{ return this.hasOwnProperty('edit') }-*/; + public final native JsArrayString hashtags() /*-{ return this.hashtags; }-*/; + + public final native boolean hasPermittedLabels() + /*-{ return this.hasOwnProperty('permitted_labels') }-*/; + public final native NativeMap<JsArrayString> permittedLabels() + /*-{ return this.permitted_labels; }-*/; + public final native JsArrayString permittedValues(String n) + /*-{ return this.permitted_labels[n]; }-*/; + + public final native JsArray<AccountInfo> removableReviewers() + /*-{ return this.removable_reviewers; }-*/; + + public final native boolean hasActions() /*-{ return this.hasOwnProperty('actions') }-*/; + public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/; + + public final native int _number() /*-{ return this._number; }-*/; + public final native boolean _more_changes() + /*-{ return this._more_changes ? true : false; }-*/; + + public final boolean submittable() { + init(); + return _submittable(); + } + + private final native boolean _submittable() + /*-{ return this.submittable ? true : false; }-*/; + + /** + * @return the index of the missing label or -1 + * if no label is missing, or if more than one label is missing. + */ + public final int getMissingLabelIndex() { + int i = -1; + int ret = -1; + List<LabelInfo> labels = Natives.asList(allLabels().values()); + for (LabelInfo label : labels) { + i++; + if (!permittedLabels().containsKey(label.name())) { + continue; + } + + JsArrayString values = permittedValues(label.name()); + if (values.length() == 0) { + continue; + } + + switch (label.status()) { + case NEED: // Label is required for submit. + if (ret != -1) { + // more than one label is missing, so it's unclear which to quick + // approve, return -1 + return -1; + } else { + ret = i; + } + continue; + + case OK: // Label already applied. + case MAY: // Label is not required. + continue; + + case REJECT: // Submit cannot happen, do not quick approve. + case IMPOSSIBLE: + return -1; + } + } + return ret; + } + + protected ChangeInfo() { + } + + public static class LabelInfo extends JavaScriptObject { + public final SubmitRecord.Label.Status status() { + if (approved() != null) { + return SubmitRecord.Label.Status.OK; + } else if (rejected() != null) { + return SubmitRecord.Label.Status.REJECT; + } else if (optional()) { + return SubmitRecord.Label.Status.MAY; + } else { + return SubmitRecord.Label.Status.NEED; + } + } + + public final native String name() /*-{ return this._name; }-*/; + public final native AccountInfo approved() /*-{ return this.approved; }-*/; + public final native AccountInfo rejected() /*-{ return this.rejected; }-*/; + + public final native AccountInfo recommended() /*-{ return this.recommended; }-*/; + public final native AccountInfo disliked() /*-{ return this.disliked; }-*/; + + public final native JsArray<ApprovalInfo> all() /*-{ return this.all; }-*/; + public final ApprovalInfo forUser(int user) { + JsArray<ApprovalInfo> all = all(); + for (int i = 0; all != null && i < all.length(); i++) { + if (all.get(i)._accountId() == user) { + return all.get(i); + } + } + return null; + } + + private final native NativeMap<NativeString> _values() /*-{ return this.values; }-*/; + public final Set<String> values() { + return Natives.keys(_values()); + } + public final native String valueText(String n) /*-{ return this.values[n]; }-*/; + + public final native boolean optional() /*-{ return this.optional ? true : false; }-*/; + public final native boolean blocking() /*-{ return this.blocking ? true : false; }-*/; + public final native short defaultValue() /*-{ return this.default_value; }-*/; + public final native short _value() + /*-{ + if (this.value) return this.value; + if (this.disliked) return -1; + if (this.recommended) return 1; + return 0; + }-*/; + + public final String maxValue() { + return LabelValue.formatValue(valueSet().last()); + } + + public final SortedSet<Short> valueSet() { + SortedSet<Short> values = new TreeSet<>(); + for (String v : values()) { + values.add(parseValue(v)); + } + return values; + } + + public static final short parseValue(String formatted) { + if (formatted.startsWith("+")) { + formatted = formatted.substring(1); + } else if (formatted.startsWith(" ")) { + formatted = formatted.trim(); + } + return Short.parseShort(formatted); + } + + protected LabelInfo() { + } + } + + public static class ApprovalInfo extends AccountInfo { + public final native boolean hasValue() /*-{ return this.hasOwnProperty('value'); }-*/; + public final native short value() /*-{ return this.value || 0; }-*/; + + protected ApprovalInfo() { + } + } + + public static class EditInfo extends JavaScriptObject { + public final native String name() /*-{ return this.name; }-*/; + public final native String setName(String n) /*-{ this.name = n; }-*/; + public final native String baseRevision() /*-{ return this.base_revision; }-*/; + public final native CommitInfo commit() /*-{ return this.commit; }-*/; + + public final native boolean hasActions() /*-{ return this.hasOwnProperty('actions') }-*/; + public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/; + + public final native boolean hasFetch() /*-{ return this.hasOwnProperty('fetch') }-*/; + public final native NativeMap<FetchInfo> fetch() /*-{ return this.fetch; }-*/; + + public final native boolean hasFiles() /*-{ return this.hasOwnProperty('files') }-*/; + public final native NativeMap<FileInfo> files() /*-{ return this.files; }-*/; + + protected EditInfo() { + } + } + + public static class RevisionInfo extends JavaScriptObject { + public static RevisionInfo fromEdit(EditInfo edit) { + RevisionInfo revisionInfo = createObject().cast(); + revisionInfo.takeFromEdit(edit); + return revisionInfo; + } + private final native void takeFromEdit(EditInfo edit) /*-{ + this._number = 0; + this.name = edit.name; + this.commit = edit.commit; + this.edit_base = edit.base_revision; + }-*/; + public final native int _number() /*-{ return this._number; }-*/; + public final native String name() /*-{ return this.name; }-*/; + public final native boolean draft() /*-{ return this.draft || false; }-*/; + public final native boolean isEdit() /*-{ return this._number == 0; }-*/; + public final native CommitInfo commit() /*-{ return this.commit; }-*/; + public final native void setCommit(CommitInfo c) /*-{ this.commit = c; }-*/; + public final native String editBase() /*-{ return this.edit_base; }-*/; + + public final native boolean hasFiles() /*-{ return this.hasOwnProperty('files') }-*/; + public final native NativeMap<FileInfo> files() /*-{ return this.files; }-*/; + + public final native boolean hasActions() /*-{ return this.hasOwnProperty('actions') }-*/; + public final native NativeMap<ActionInfo> actions() /*-{ return this.actions; }-*/; + + public final native boolean hasFetch() /*-{ return this.hasOwnProperty('fetch') }-*/; + public final native NativeMap<FetchInfo> fetch() /*-{ return this.fetch; }-*/; + + public static void sortRevisionInfoByNumber(JsArray<RevisionInfo> list) { + final int editParent = findEditParent(list); + Collections.sort(Natives.asList(list), new Comparator<RevisionInfo>() { + @Override + public int compare(RevisionInfo a, RevisionInfo b) { + return num(a) - num(b); + } + + private int num(RevisionInfo r) { + return !r.isEdit() ? 2 * (r._number() - 1) + 1 : 2 * editParent; + } + }); + } + + public static int findEditParent(JsArray<RevisionInfo> list) { + for (int i = 0; i < list.length(); i++) { + // edit under revisions? + RevisionInfo editInfo = list.get(i); + if (editInfo.isEdit()) { + String parentRevision = editInfo.editBase(); + // find parent + for (int j = 0; j < list.length(); j++) { + RevisionInfo parentInfo = list.get(j); + String name = parentInfo.name(); + if (name.equals(parentRevision)) { + // found parent pacth set number + return parentInfo._number(); + } + } + } + } + return -1; + } + + public final String id() { + return PatchSet.Id.toId(_number()); + } + + protected RevisionInfo () { + } + } + + public static class FetchInfo extends JavaScriptObject { + public final native String url() /*-{ return this.url }-*/; + public final native String ref() /*-{ return this.ref }-*/; + public final native NativeMap<NativeString> commands() /*-{ return this.commands }-*/; + public final native String command(String n) /*-{ return this.commands[n]; }-*/; + + protected FetchInfo () { + } + } + + public static class CommitInfo extends JavaScriptObject { + public final native String commit() /*-{ return this.commit; }-*/; + public final native JsArray<CommitInfo> parents() /*-{ return this.parents; }-*/; + public final native GitPerson author() /*-{ return this.author; }-*/; + public final native GitPerson committer() /*-{ return this.committer; }-*/; + public final native String subject() /*-{ return this.subject; }-*/; + public final native String message() /*-{ return this.message; }-*/; + public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/; + + protected CommitInfo() { + } + } + + public static class GitPerson extends JavaScriptObject { + public final native String name() /*-{ return this.name; }-*/; + public final native String email() /*-{ return this.email; }-*/; + private final native String dateRaw() /*-{ return this.date; }-*/; + + public final Timestamp date() { + return JavaSqlTimestamp_JsonSerializer.parseTimestamp(dateRaw()); + } + + protected GitPerson() { + } + } + + public static class MessageInfo extends JavaScriptObject { + public final native AccountInfo author() /*-{ return this.author; }-*/; + public final native String message() /*-{ return this.message; }-*/; + public final native int _revisionNumber() /*-{ return this._revision_number || 0; }-*/; + private final native String dateRaw() /*-{ return this.date; }-*/; + + public final Timestamp date() { + return JavaSqlTimestamp_JsonSerializer.parseTimestamp(dateRaw()); + } + + protected MessageInfo() { + } + } + + public static class MergeableInfo extends JavaScriptObject { + public final native String submitType() /*-{ return this.submit_type }-*/; + public final native boolean mergeable() /*-{ return this.mergeable }-*/; + + protected MergeableInfo() { + } + } + + public static class IncludedInInfo extends JavaScriptObject { + public final Set<String> externalNames() { + return Natives.keys(external()); + } + + public final native JsArrayString branches() /*-{ return this.branches; }-*/; + public final native JsArrayString tags() /*-{ return this.tags; }-*/; + public final native JsArrayString external(String n) /*-{ return this.external[n]; }-*/; + private final native NativeMap<JsArrayString> external() /*-{ return this.external; }-*/; + + protected IncludedInInfo() { + } + } +} diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/FileInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/FileInfo.java new file mode 100644 index 0000000..b21078e --- /dev/null +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/FileInfo.java
@@ -0,0 +1,74 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.client.info; + +import com.google.gerrit.client.rpc.Natives; +import com.google.gerrit.reviewdb.client.Patch; +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArray; + +import java.util.Collections; +import java.util.Comparator; + +public class FileInfo extends JavaScriptObject { + public final native String path() /*-{ return this.path; }-*/; + public final native String oldPath() /*-{ return this.old_path; }-*/; + public final native int linesInserted() /*-{ return this.lines_inserted || 0; }-*/; + public final native int linesDeleted() /*-{ return this.lines_deleted || 0; }-*/; + public final native boolean binary() /*-{ return this.binary || false; }-*/; + public final native String status() /*-{ return this.status; }-*/; + + public final native int _row() /*-{ return this._row }-*/; + public final native void _row(int r) /*-{ this._row = r }-*/; + + public static void sortFileInfoByPath(JsArray<FileInfo> list) { + Collections.sort(Natives.asList(list), new Comparator<FileInfo>() { + @Override + public int compare(FileInfo a, FileInfo b) { + if (Patch.COMMIT_MSG.equals(a.path())) { + return -1; + } else if (Patch.COMMIT_MSG.equals(b.path())) { + return 1; + } + // Look at file suffixes to check if it makes sense to use a different order + int s1 = a.path().lastIndexOf('.'); + int s2 = b.path().lastIndexOf('.'); + if (s1 > 0 && s2 > 0 && + a.path().substring(0, s1).equals(b.path().substring(0, s2))) { + String suffixA = a.path().substring(s1); + String suffixB = b.path().substring(s2); + // C++ and C: give priority to header files (.h/.hpp/...) + if (suffixA.indexOf(".h") == 0) { + return -1; + } else if (suffixB.indexOf(".h") == 0) { + return 1; + } + } + return a.path().compareTo(b.path()); + } + }); + } + + public static String getFileName(String path) { + String fileName = Patch.COMMIT_MSG.equals(path) + ? "Commit Message" + : path; + int s = fileName.lastIndexOf('/'); + return s >= 0 ? fileName.substring(s + 1) : fileName; + } + + protected FileInfo() { + } +} diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/WebLinkInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/WebLinkInfo.java new file mode 100644 index 0000000..367486b --- /dev/null +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/WebLinkInfo.java
@@ -0,0 +1,48 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.client.info; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.Image; + +public class WebLinkInfo extends JavaScriptObject { + + public final native String name() /*-{ return this.name; }-*/; + public final native String imageUrl() /*-{ return this.image_url; }-*/; + public final native String url() /*-{ return this.url; }-*/; + public final native String target() /*-{ return this.target; }-*/; + + protected WebLinkInfo() { + } + + public final Anchor toAnchor() { + Anchor a = new Anchor(); + a.setHref(url()); + if (target() != null && !target().isEmpty()) { + a.setTarget(target()); + } + if (imageUrl() != null && !imageUrl().isEmpty()) { + Image img = new Image(); + img.setAltText(name()); + img.setUrl(imageUrl()); + img.setTitle(name()); + a.getElement().appendChild(img.getElement()); + } else { + a.setText("(" + name() + ")"); + } + return a; + } +}